1 /*
2  * Collie - An asynchronous event-driven network framework using Dlang development
3  *
4  * Copyright (C) 2015-2017  Shanghai Putao Technology Co., Ltd 
5  *
6  * Developer: putao's Dlang team
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 module collie.codec.http.headers.httpcommonheaders;
12 
13 import collie.utils.string;
14 
15 alias HttpHeaderCode = HTTPHeaderCode;
16 
17 enum HTTPHeaderCode : ubyte {
18 	// code reserved to indicate the absence of an HTTP header
19 	NONE = 0,
20 	// code for any HTTP header name not in the list of common headers
21 	OTHER = 1,
22 
23 	ACCEPT = 2,
24 	ACCEPT_CHARSET = 3,
25 	ACCEPT_DATETIME = 4,
26 	ACCEPT_ENCODING = 5,
27 	ACCEPT_LANGUAGE = 6,
28 	ACCEPT_RANGES = 7,
29 	ACCESS_CONTROL_ALLOW_CREDENTIALS = 8,
30 	ACCESS_CONTROL_ALLOW_HEADERS = 9,
31 	ACCESS_CONTROL_ALLOW_METHODS = 10,
32 	ACCESS_CONTROL_ALLOW_ORIGIN = 11,
33 	ACCESS_CONTROL_EXPOSE_HEADERS = 12,
34 	ACCESS_CONTROL_MAX_AGE = 13,
35 	ACCESS_CONTROL_REQUEST_HEADERS = 14,
36 	ACCESS_CONTROL_REQUEST_METHOD = 15,
37 	AGE = 16,
38 	ALLOW = 17,
39 	ALT_SVC = 18,
40 	AUTHORIZATION = 19,
41 	CACHE_CONTROL = 20,
42 	CONNECTION = 21,
43 	CONTENT_DISPOSITION = 22,
44 	CONTENT_ENCODING = 23,
45 	CONTENT_LANGUAGE = 24,
46 	CONTENT_LENGTH = 25,
47 	CONTENT_LOCATION = 26,
48 	CONTENT_MD5 = 27,
49 	CONTENT_RANGE = 28,
50 	CONTENT_TYPE = 29,
51 	COOKIE = 30,
52 	DNT = 31,
53 	DATE = 32,
54 	ETAG = 33,
55 	EXPECT = 34,
56 	EXPIRES = 35,
57 	FROM = 36,
58 	FRONT_END_HTTPS = 37,
59 	HOST = 38,
60 	IF_MATCH = 39,
61 	IF_MODIFIED_SINCE = 40,
62 	IF_NONE_MATCH = 41,
63 	IF_RANGE = 42,
64 	IF_UNMODIFIED_SINCE = 43,
65 	KEEP_ALIVE = 44,
66 	LAST_MODIFIED = 45,
67 	LINK = 46,
68 	LOCATION = 47,
69 	MAX_FORWARDS = 48,
70 	ORIGIN = 49,
71 	P3P = 50,
72 	PRAGMA = 51,
73 	PROXY_AUTHENTICATE = 52,
74 	PROXY_AUTHORIZATION = 53,
75 	PROXY_CONNECTION = 54,
76 	RANGE = 55,
77 	REFERER = 56,
78 	REFRESH = 57,
79 	RETRY_AFTER = 58,
80 	SERVER = 59,
81 	SET_COOKIE = 60,
82 	STRICT_TRANSPORT_SECURITY = 61,
83 	TE = 62,
84 	TIMESTAMP = 63,
85 	TRAILER = 64,
86 	TRANSFER_ENCODING = 65,
87 	UPGRADE = 66,
88 	USER_AGENT = 67,
89 	VIP = 68,
90 	VARY = 69,
91 	VIA = 70,
92 	WWW_AUTHENTICATE = 71,
93 	WARNING = 72,
94 	X_ACCEL_REDIRECT = 73,
95 	X_CONTENT_SECURITY_POLICY_REPORT_ONLY = 74,
96 	X_CONTENT_TYPE_OPTIONS = 75,
97 	X_FORWARDED_FOR = 76,
98 	X_FORWARDED_PROTO = 77,
99 	X_FRAME_OPTIONS = 78,
100 	X_POWERED_BY = 79,
101 	X_REAL_IP = 80,
102 	X_REQUESTED_WITH = 81,
103 	X_UA_COMPATIBLE = 82,
104 	X_WAP_PROFILE = 83,
105 	X_XSS_PROTECTION = 84,
106 	SEC_WEBSOCKET_KEY = 85,
107 	SEC_WEBSOCKET_VERSION = 86,
108 	SEC_WEBSOCKET_LOCATION = 87,
109 	SEC_WEBSOCKET_ACCEPT = 88
110 }
111 
112 mixin(buildEnum!HTTPHeaderCode());
113 
114 string capitalizeHeader(string name)
115 {
116 	import std.uni;
117 	import std.array;
118 	import std.string;
119 	string[] parts = name.split("_");
120 	for (int i = 0; i < parts.length; i++)
121 	{
122 		parts[i] = parts[i].capitalize;
123 	}
124 	return join(parts, "-");
125 }
126 private:
127 string buildEnum(T)()
128 {
129 	import std.uni;
130 	import std.array;
131 	import std.conv;
132 	struct TMPV{
133 		string name;
134 		string value; 
135 	}
136 	TMPV[][] list;
137 	list.length = ubyte.max;
138 	string codename = "enum string[] HTTPHeaderCodeName = [";
139 	foreach(m; __traits(derivedMembers,T))
140 	{
141 		string str = capitalizeHeader(m);
142 		str = str.replace("_","-");
143 		codename ~= "\"" ~ str ~ "\","; 
144 		list[str.length] ~= TMPV(str,m);
145 	}
146 	codename = codename[0..codename.length - 1];
147 	codename ~= "];\n ";
148 	string funn = "HTTPHeaderCode headersHash(string name){\n HTTPHeaderCode code = HTTPHeaderCode.OTHER; \n switch (name.length) {\n";
149 	foreach(size_t index,TMPV[] ls; list)
150 	{
151 		if(ls.length > 0) {
152 			funn ~= "case " ~ to!string(index) ~ " : {\n";
153 			foreach(ref TMPV st;ls)
154 			{
155 				funn ~= "if(isSameIngnoreLowUp(name,\"" ~ st.name ~ "\" )){ code = HTTPHeaderCode."~ st.value ~ "; break;}\n";
156 			}
157 			funn ~= "\n} break;\n";
158 		}
159 	}
160 	funn ~= "default: break;}\n return code;}\n";
161 	return codename ~ funn;
162 }
163 
164 
165 unittest
166 {
167 	assert(headersHash("age") == HTTPHeaderCode.AGE);
168 	assert(headersHash("Age") == HTTPHeaderCode.AGE);
169 	assert(headersHash("MY-HEADER") == HTTPHeaderCode.OTHER);
170 	assert(headersHash("DNT") == HTTPHeaderCode.DNT);
171 }